package com.lqf.redpackage.service.impl;

import com.lqf.redpackage.dao.TRedPacketMapper;
import com.lqf.redpackage.dao.TUserRedPacketMapper;
import com.lqf.redpackage.domain.TRedPacket;
import com.lqf.redpackage.domain.TUserRedPacket;
import com.lqf.redpackage.service.UserRedPacketService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;

@Service
public class UserRedPacketServiceImpl implements UserRedPacketService {


    @Autowired
    private TUserRedPacketMapper userRedPacketMapper;

    @Autowired
    private TRedPacketMapper redPacketMapper;

    // 失败
    private static final int FAILED = 0;

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public int grapRedPacket(Long redPacketId, Long userId) {
        // 获取红包信息--并发存在超发
//        TRedPacket redPacket = redPacketMapper.getRedPacket(redPacketId);
        //悲观锁方式获取红包记录保证不出现超发现象
        TRedPacket redPacket = redPacketMapper.getRedPacket(redPacketId);
        int leftRedPacket = redPacket.getStock();
        // 当前小红包库存大于0
        if (leftRedPacket > 0) {
            redPacketMapper.decreaseRedPacket(redPacketId);
            // logger.info("剩余Stock数量:{}", leftRedPacket);
            // 生成抢红包信息
            TUserRedPacket userRedPacket = new TUserRedPacket();
            userRedPacket.setRedPacketId(redPacketId.intValue());
            userRedPacket.setUserId(userId.intValue());
            userRedPacket.setAmount(BigDecimal.valueOf(redPacket.getUnitAmount()));
            userRedPacket.setNote("redpacket- " + redPacketId);
            // 插入抢红包信息
            int result = userRedPacketMapper.grapRedPacket(userRedPacket);
            return result;
        }
        // logger.info("没有红包啦.....剩余Stock数量:{}", leftRedPacket);
        // 失败返回
        return FAILED;
    }



    /**
     * 乐观锁，无重入
     * */
    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
    public int grapRedPacketForVersion(Long redPacketId, Long userId) {
        for (int i = 0; i < 3; i++) {
            // 获取红包信息，注意version值
            TRedPacket redPacket = redPacketMapper.getRedPacket(redPacketId);
            // 当前小红包库存大于0
            if (redPacket.getStock() > 0) {
                // 再次传入线程保存的version旧值给SQL判断，是否有其他线程修改过数据
                int update = redPacketMapper.decreaseRedPacketForVersion(redPacketId, redPacket.getVersion());
                // 如果没有数据更新，则说明其他线程已经修改过数据，则重新抢夺
                if (update == 0) {
                    continue;
                }
                // 生成抢红包信息
                TUserRedPacket userRedPacket = new TUserRedPacket();
                userRedPacket.setRedPacketId(redPacketId.intValue());
                userRedPacket.setUserId(userId.intValue());
                userRedPacket.setAmount(BigDecimal.valueOf(redPacket.getUnitAmount()));
                userRedPacket.setNote("抢红包 " + redPacketId);
                // 插入抢红包信息
                int result = userRedPacketMapper.grapRedPacket(userRedPacket);
                return result;
            } else {
                // 一旦没有库存，则马上返回
                return FAILED;
            }
        }
        return FAILED;
    }


}

